AWS Lambda の新機能でサーバーレス・シェルスクリプト! カスタムランタイムのチュートリアルを動かしてみた #reinvent
待望のサーバーレスシェルスクリプト環境!?
既報ですが、AWS re:Invent 2018 のキーノート Day 2 にて AWS Lambda に新機能、Custom Runtime が発表になりました!
【アップデート】 もう言語で悩まない!AWS LambdaでCustom Runtimeが利用できるようになりました! #reinvent
- New for AWS Lambda – Use Any Programming Language and Share Common Components | AWS News Blog
- AWS Lambda Now Supports Custom Runtimes, and Enables Sharing Common Code Between Functions
思えば以前から、仕様の隙を突いてごにょごにょすることで Lambda 上で好きなバイナリを動かすことは出来たわけですが、この機能が発表されたことで、もうそんなことする必要も、それをプロダクションレベルで使って良いかどうか考える必要もないわけですね。公式サポート素晴らしいです。
技術情報としては下記のドキュメントがそろっています(まだ英語ですが)。また勿論、既存のドキュメントから得られる環境変数の値などの情報もそろっているわけで、すぐにでも使い始められますね。
ひとまずチュートリアルを動かしてみることにします!
チュートリアルドキュメントを眺めてみる
公式ドキュメントに、カスタムランタイムを動かすためのチュートリアルが用意されています。
こちらとLambda の実行環境のドキュメント、ならびに先にあげた Custom AWS Lambda Runtimes のドキュメント等を合わせ読むと、こんな感じのことが読み取れました。
- ランタイム
bootstrap
と function handlerfunction.sh
、ふたつのファイルを用意する bootstrap
というがまず実行される- ぱっとみ
function.sh
は別に分ける必要ないのでは?? - OS は Amazon Linux (AL2ではない)
/usr/bin
がある- というか
PATH
からすると/usr/bin
も/usr/local/bin
も/opt/bin
もある sh
が Amazon Linux のものと同じなら、少なくとも Bash のビルトインコマンド は使えそう?
- というか
grep
とかcurl
とかある。基本的なものは一通りそろってそう- 環境変数でもろもろ取得できそう
$LAMBDA_TASK_ROOT
の下に行けば、パッケージされたファイルが呼び出せそう- Lambda Runtime API を叩いて何かを送受信している
とまあ、もっと深読みできるとは思うのですが、眺めるのはその辺にして、ひとまずチュートリアルを実行してみます。
やってみる
チュートリアルは AWS CLI で行うかたちになってましたが、とりあえずマネジメントコンソールで始めてみましょう。
今回は macOS Mojave で作業しています。Windows 環境の場合は WSL などの Linux 互換環境を用意するようにとチュートリアルにありましたので、そのようにしましょう(恐らく chmod する関係かと想像しています)。
関数の作成
まずは関数の作成を行います。マネジメントコンソールにログイン、 AWS Lambda のコンソールから「関数の作成」をクリックします。
さすがにシェルスクリプトの設計図はなかったので、素直に「一から作成」をクリックしました。
必要な項目を埋めます。
項目名 | 値 |
---|---|
名前 | lambda-custom-runtime-tutorial |
ランタイム | 独自のランタイムを使用する |
ロール | 1つ以上のテンプレートから新しいロールを作成します。 |
ロール名 | lambda-custom-runtime-tutorial-role |
名前(関数名)とロール名は任意です。今回は分かるようにこんな名前にしました。
ロール作成時にテンプレートから選ぶようにしたので、適当に「Amazon S3 オブジェクトの読み取り専用アクセス権限」を選択しました。もちろん チュートリアル に忠実に、AWSLambdaBasicExecutionRole
を含む IAM ロールをカスタムで作成しても良いと思います。というかそっちが本当ですねw
問題なければ「関数の作成」をクリックします。
しばらく待った後、見慣れた初期画面に遷移しました。ここからチュートリアルの内容にいろいろと置き換えていきます。
ここで画面を良く見ると、カスタムランタイムを選ぶとインラインエディタ(Cloud9)が使えないみたいです。というわけで、コードが含まれた Zip ファイル(パッケージ)を用意します。
パッケージの用意とアップロード
上に書いたとおり、bootstrap
と function.sh
の二つのファイルを用意します。適当なテキストエディタで、ドキュメントのとおり作成しました(若干書き方が違っているのは shfmt
を通したからです、ご了承下さい)。
#!/bin/sh set -euo pipefail # Initialization - load function handler source $LAMBDA_TASK_ROOT/"$(echo $_HANDLER | cut -d. -f1).sh" # Processing while true; do HEADERS="$(mktemp)" # Get an event EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next") REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2) # Execute the handler function from the script RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA") # Send the response curl -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE" done
function handler() { EVENT_DATA=$1 echo "$EVENT_DATA" 1>&2 RESPONSE="Echoing request: '$EVENT_DATA'" echo $RESPONSE }
$ ls -lA total 16 -rw-r--r-- 1 watanabe.seigo staff 674 11 29 12:49 bootstrap -rw-r--r-- 1 watanabe.seigo staff 127 11 29 12:49 function.sh
そしたらこれをパッケージにします。
$ chmod 755 function.sh bootstrap $ zip lambda-custom-runtime-tutorial.zip function.sh bootstrap adding: function.sh (deflated 24%) adding: bootstrap (deflated 38%) $ ls -lAF total 24 -rwxr-xr-x 1 watanabe.seigo staff 674 11 29 12:49 bootstrap* -rwxr-xr-x 1 watanabe.seigo staff 127 11 29 12:49 function.sh* -rw-r--r-- 1 watanabe.seigo staff 829 11 29 12:53 lambda-custom-runtime-tutorial.zip
できあがったこの Zip ファイルを、Lambda コンソールからアップロード・保存します。コードエントリタイプを「.zip ファイルをアップロード」、関数パッケージの「アップロード」をクリックし、先ほど作成した Zip ファイルを指定します。
そして同時に、ハンドラーの指定を変更します。今は Hello World 仕様になっているので、これをfunction.handler
に変更します。
準備が出来たら「保存」をクリックして下さい。
以上で準備完了です!
実行(テスト)
そしたらさっそく実行・・・の前にテスト設定を行います。右上の「テスト」をクリックしましょう。
イベントテンプレート「Hello World」、イベント名に適当な名前を付けて実行します。
設定できたら、再度「テスト」をクリックします!
見事に実行されました!
CloudWatch Logs にもちゃんと出力されていますね。
結果を眺めると、下記のことが分かります。
- Lambda から出力(実行によって返された結果)は、スクリプト
bootstrap
内で環境変数$RESPONSE
の内容- 19行目の
curl
から API へ POST されたもの
- 19行目の
- 逆算すると、テストから入力された内容(JSON)は 12行目の
curl
が API から GET したものらしい - 標準出力も普通にログに出ている(
curl
の実行ログも!)
こいつはいろいろと夢が膨らみます!
まとめ
今回はチュートリアルスクリプトを実行しただけですが、得られた結果からいろいろそぎ落としたり正規化したりしていけば、いろいろと手軽に処理が実行できるようになりそうです。もうすこし触っていて、後日あらためて深掘りした結果をアウトプットしたいと思います!